package cs236369.webserver;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 *	This class centers all the XML parsing capabilities 
 * 	In the construction process exceptions may be thrown.
 */
//TODO add all xpath queries
public class Parser {

	Document parsedConfig = null;
	XPath xpath = null;
	
	Parser(InputStream config) throws
								ParserConfigurationException, 
								SAXException, 
								IOException {

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(false); //TODO ask if it's ok not to validate
		factory.setIgnoringElementContentWhitespace(true); //TODO ask if it's ok to do that
		DocumentBuilder builder = factory.newDocumentBuilder();
		parsedConfig = builder.parse(config);
		
		XPathFactory xpathFactory = XPathFactory.newInstance();
		xpath = xpathFactory.newXPath();
	}
	
	private String getAttributeByParent(String parent,
										String attribute) 
										throws 
										XPathExpressionException {
		return xpath.compile("//" + parent + "/@" + attribute).
						evaluate(parsedConfig);
	}
	
	private String getNodeByParent(String parent,
								String element) 
								throws 
								XPathExpressionException {
		return 	xpath.compile("//" + parent + "/" + element).
									evaluate(parsedConfig);
	}
	
	/**
	 * @return an absolute path in the file system that represents 
	 * 			the route of the base directory of the file system
	 * @throws XPathExpressionException 
	 */
	String getBaseDirectory() throws XPathExpressionException {
		return getAttributeByParent("server-config", "base");
	}
	
	/**
	 * @return the port the server listens to
	 * @throws XPathExpressionException
	 */
	int getPort() throws XPathExpressionException {
		String port = getAttributeByParent("server-config", "port");
		return Integer.parseInt(port);
	}
	
	
	/**
	 * @return the number of socket-readers threads
	 * @throws XPathExpressionException
	 */
	int getNumSocketReaders() throws XPathExpressionException {
		String numSocketReaders = getNodeByParent("socket-readers", "multi");
		return Integer.parseInt(numSocketReaders); 
		
	}
	
	/**
	 * @return the number of request-reader threads
	 * @throws XPathExpressionException
	 */
	int getNumRequestReaders() throws XPathExpressionException {
		String numRequestReaders = getNodeByParent("request-handlers", "multi");
		return Integer.parseInt(numRequestReaders); 
	}
	
	/**
	 * @return the size of the queue holding the connection socket objects 
	 * @throws XPathExpressionException
	 */
	int getNumSocketQueue() throws XPathExpressionException {
		String numSockets = getNodeByParent("socket-queue","size");
		return Integer.parseInt(numSockets); 
	}
	
	/**
	 * @return the size of the queue holding the request objects
	 * @throws XPathExpressionException
	 */
	int getNumRequestQueue() throws XPathExpressionException {
		String numRequests = getNodeByParent("request-queue", "size");
		return Integer.parseInt(numRequests);
	}
}
